# -*- coding: utf-8 -*-

from fastapi import APIRouter, Depends, Header, HTTPException
from typing import List, Optional

chapter03 = APIRouter()

""" Dependencies 创建、导入、声明 依赖"""


async def common_parameters(q: Optional[str] = None, page: int = 1, limit: int = 100):
    return {"q": q, "page": page, "limit": limit}

@chapter03.get('/dependency01')
async def dependency01(commons: dict = Depends(common_parameters)):
    return commons

@chapter03.get('/dependency02')
def dependency02(commons: dict = Depends(common_parameters)):
    return commons

""" Classes as Dependencies 类作为依赖"""

fake_items_db = [
    {"item_name": "Tom"},
    {"item_name": "Jerry"},
    {"item_name": "Lily"}
]


class CommonQueryParams:
    def __init__(self, q: Optional[str] = None, page: int = 1, limit: int = 100):
        self.q = q
        self.page = page
        self.limit = limit

@chapter03.get('/classes_as_dependencies')
# async def classes_as_dependencies(commons: CommonQueryParams = Depends(CommonQueryParams))
# async def classes_as_dependencies(commons: CommonQueryParams = Depends())
async def classes_as_dependencies(commons = Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.page: commons.page + commons.limit]
    response.update({"items": items})
    return response

""" Sub-dependencies 子依赖 """
def query(q: Optional[str] = None):
    return q

def sub_query(q: str = Depends(query), last_query: Optional[str] = None):
    if not q:
        return last_query
    return q

@chapter03.get('/sub_dependency')
async def sub_dependency(final_query: str = Depends(sub_query, use_cache=True)):
    """
    use_cache默认是True，表示多个依赖又共同一个子依赖式时，每次request请求只会调用一次子依赖
    :param final_query:
    :return:
    """
    return {"sub_dependency": final_query}

"""Dependencies in path operation decorators 路径操作装饰器中的依赖"""
async def verify_token(x_token: str = Header(...)):
    """
    没有返回值的子依赖
    :param x_token:
    :return:
    """
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="X-Token header invalid")
    return x_token


async def verify_key(x_key: str = Header(...)):
    """
    有返回值的子依赖，但是返回值不会被调用
    :param x_token:
    :return:
    """
    if x_key != "fake-super-secret-key":
        raise HTTPException(status_code=400, detail="X-Key header invalid")
    return x_key

@chapter03.get('/dependency_in_path_operation', dependencies=[Depends(verify_key), Depends(verify_token)])
async def dependency_in_path_operation():
    return [{"user": "user01"}, {"user": "user02"}]

"""Global Dependencies 全局依赖"""
# app03 = APIRouter(dependencies=[Depends(verify_key), Depends(verify_token)])

"""Dependencies with yield 带yield的依赖"""
# pip install async-exit-stack async - generator
async def get_db():
    db = "db_conntection"
    try:
        yield db
    finally:
        db.endswith("db_close")

async def generate_dep_a():
    dep_a = "generate_dep_a"
    try:
        yield dep_a
    finally:
        dep_a.endswith("db_close")

async def generate_dep_b(dep_a=Depends(generate_dep_a)):
    dep_b = "generate_dep_b"
    try:
        yield dep_b
    finally:
        dep_b.endswith("db_close")

async def generate_dep_c(dep_b=Depends(generate_dep_b)):
    dep_c = "generate_dep_c"
    try:
        yield dep_c
    finally:
        dep_c.endswith("db_close")

